using System;
using IQIGame.Onigao.Framework;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 对Animator进行一层封装，实际上内部还是完全针对Animator的Api进行重新实现
    /// 设计目的是为了让简单的Animator能处理更复杂的动画播放需求
    /// 例如SetTrigger和CrossFade时派发事件，支持多动画协同；支持实体在玩家视野外模型被卸载后，动画逻辑依旧可以空转，实现显示清空逻辑不停的需求。
    /// </summary>
    public abstract class AnimatorAgent : IReusableClass
    {
        public Animator animator { get; set; }
        public virtual uint MaxStore { get; }

        public virtual bool isActiveAndEnabled => animator != null ? animator.isActiveAndEnabled : false;
        public virtual bool HasState(int layerIndex, int stateID) => animator != null ? animator.HasState(layerIndex, stateID) : false;
        public virtual float GetFloat(int id) => animator != null ? animator.GetFloat(id) : 0;

        public virtual void CrossFade(int stateHashName, float normalizedTransitionDuration, int layer, float normalizedTimeOffset)
        {
            CrossFade(stateHashName, normalizedTransitionDuration, layer, normalizedTimeOffset, 0);
        }

        public virtual void CrossFade(int stateHashName, float normalizedTransitionDuration)
        {
            CrossFade(stateHashName, normalizedTransitionDuration, -1, float.NegativeInfinity, 0);
        }

        public virtual void CrossFade(int stateHashName, float normalizedTransitionDuration, int layer, float normalizedTimeOffset, float normalizedTransitionTime)
        {
            if (animator != null)
            {
                animator.CrossFade(stateHashName, normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime);
            }
        }

        public virtual void SetTrigger(int id)
        {
            if (animator != null)
            {
                animator.SetTrigger(id);
            }
        }

        public virtual void SetBool(int id, bool value)
        {
            if (animator != null)
            {
                animator.SetBool(id, value);
            }
        }

        public virtual void SetFloat(int id, float value)
        {
            if (animator != null)
            {
                animator.SetFloat(id, value);
            }
        }

        public virtual void OnReset()
        {
            animator = null;
        }
    }

    /// <summary>
    /// 可派发事件的Animator
    /// 如为小宠物动画协同提供支持，小宠物的IAnimator接受到事件后可同步动作
    /// </summary>
    public class EventAnimator : AnimatorAgent
    {
        public delegate void DeleCrossFade(int stateHashName, float normalizedTransitionDuration,
            int layer, float normalizedTimeOffset, float normalizedTransitionTime);
        public event DeleCrossFade onCrossFade;
        public event Action<int> onSetTrigger;
        public event Action<int, bool> onSetBool;
        public event Action<int, float> onSetFloat;
        public override uint MaxStore => 100;

        public override void CrossFade(int stateHashName, float normalizedTransitionDuration, int layer, float normalizedTimeOffset, float normalizedTransitionTime)
        {
            base.CrossFade(stateHashName, normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime);
            onCrossFade?.Invoke(stateHashName, normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime);
        }

        public override void SetTrigger(int id)
        {
            base.SetTrigger(id);
            onSetTrigger?.Invoke(id);
        }

        public override void SetBool(int id, bool value)
        {
            base.SetBool(id, value);
            onSetBool?.Invoke(id, value);
        }

        public override void SetFloat(int id, float value)
        {
            base.SetFloat(id, value);
            onSetFloat?.Invoke(id, value);
        }
    }

    /// <summary>
    /// 同步动画播放器
    /// source调用动画切换方法时，本方法也执行相同的逻辑
    /// </summary>
    public class SyncAnimator : AnimatorAgent
    {
        public EventAnimator source { get; private set; }
        public override uint MaxStore => 20;

        public virtual void Subscribe(EventAnimator source)
        {
            if (source == null)
            {
                LogGame.LogError($"订阅同步动画失败，source == null。");
                return;
            }
            this.source = source;
            this.source.onCrossFade += OnCrossFade;
            this.source.onSetTrigger += OnSetTrigger;
            this.source.onSetBool += OnSetBool;
            this.source.onSetFloat += OnSetFloat;
        }

        public virtual void Unsubscribe()
        {
            if (source == null)
            {
                return;
            }
            source.onCrossFade -= OnCrossFade;
            source.onSetTrigger -= OnSetTrigger;
            source.onSetBool -= OnSetBool;
            source.onSetFloat -= OnSetFloat;
            source = null;
        }

        #region source事件响应函数
        public virtual void OnCrossFade(int stateHashName, float normalizedTransitionDuration, int layer, float normalizedTimeOffset, float normalizedTransitionTime)
        {
            CrossFade(stateHashName, normalizedTransitionDuration, layer, normalizedTimeOffset, normalizedTransitionTime);
        }

        public virtual void OnSetTrigger(int id)
        {
            SetTrigger(id);
        }

        public virtual void OnSetBool(int id, bool value)
        {
            SetBool(id, value);
        }

        public virtual void OnSetFloat(int id, float value)
        {
            SetFloat(id, value);
        }
        #endregion source事件响应函数

        public override void OnReset()
        {
            Unsubscribe();
            base.OnReset();
        }
    }

    /// <summary>
    /// 除了移动都同步的同步动画
    /// </summary>
    public class SyncAnimatorExceptMove : SyncAnimator
    {
        public override void OnSetFloat(int id, float value)
        {
            if (id == AnimationConst.Param_Speed)
            {
                return;
            }
            base.OnSetFloat(id, value);
        }
    }
}